package com.ibm.member.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.stereotype.Repository;

import com.ibm.member.common.util.BeanUtil;
import com.ibm.member.common.util.DateUtil;
import com.ibm.member.dao.BaseDao;
import com.ibm.member.model.BaseBO;
import com.ibm.member.model.comm.Pagination;
import com.ibm.member.model.comm.PaginationResult;

@Repository
public class BaseDaoImpl implements BaseDao {

    @Autowired
    private HibernateTemplate hibernateTemplate;

    @Autowired
    private SqlSessionTemplate mybatisTemplate;

    public long create(BaseBO bo) {
        bo.setCreateTime(DateUtil.newDate());
        return (long) hibernateTemplate.save(bo);
    }

    public boolean merge(BaseBO newBo) {
        BaseBO oldBo = get(newBo);
        if (oldBo != null) {
            BeanUtil.copyBeanNotNull(newBo, oldBo);
            BaseBO result = hibernateTemplate.merge(oldBo);
            return result != null;
        }
        return false;
    }

    public void update(BaseBO bo) {
        bo.setUpdateTime(DateUtil.newDate());
        hibernateTemplate.update(bo);
    }

    public void delete(BaseBO bo) {
        hibernateTemplate.delete(bo);
    }

    public <T extends BaseBO> T selectOne(BaseBO bo) {
        StringBuilder sb = new StringBuilder();
        sb.append(bo.getClass().getName());
        sb.append(".").append("get");

        Map<String, Object> param = BeanUtil.toMapNotNull(bo);
        if (param.isEmpty())
            return null;
        return mybatisTemplate.selectOne(sb.toString(), param);
    }

    public <T extends BaseBO> T get(T bo) {
        return (T) hibernateTemplate.findByExample(bo).get(0);
    }

    public <T extends BaseBO> List<T> find(T bo) {
        List<T> result = hibernateTemplate.findByExample(bo);
        if (result != null && !result.isEmpty())
            return result;
        return null;
    }

    public <T extends BaseBO> List<T> findM(T bo) {

        StringBuilder sb = new StringBuilder();
        sb.append(bo.getClass().getName());
        sb.append(".").append("find");

        Map<String, Object> param = BeanUtil.toMapNotNull(bo);
        if (param.isEmpty())
            return null;
        return mybatisTemplate.selectList(sb.toString(), param);
    }

    public <T extends BaseBO> PaginationResult<T> find(T bo, Pagination pagination) {
        List<T> r = hibernateTemplate.findByExample(bo, pagination.getFirstRowIndex(), pagination.getPagesize());
        return new PaginationResult<T>(r, pagination);
    }

    protected static <T, S> PaginationResult<T> to(PaginationResult<S> bop, Class<T> clazz) {
        PaginationResult<T> vop = new PaginationResult<>();
        vop.setPagination(bop.getPagination());

        List<S> bos = bop.getR();
        List<T> vos = new ArrayList<T>(bos.size());
        vop.setR(vos);

        for (S bo : bos) {
            T vo = newInstance(clazz);
            BeanUtil.copyBean(bo, vo);
            vos.add(vo);
        }
        return vop;
    }

    private static <T> T newInstance(Class<T> clazz) {
        try {
            return clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    protected static Map<String, Object> newMap(Object... objs) {
        Map<String, Object> result = new HashMap<String, Object>(objs.length / 2);
        for (int i = 0; i < objs.length; i += 2) {
            String key = String.valueOf(objs[i]);
            Object value = objs[i + 1];
            if (value == null)
                value = "";
            result.put(key, value);
        }
        return result;
    }
}